<?php
declare (strict_types = 1);

namespace app\common\model\system;

use app\admin\traits\GetTableData;
use app\common\components\IpLocation;
use app\common\model\content\Article;
use app\common\model\content\Tag;
use app\common\model\content\Topic;
use app\common\model\user\User;
use think\facade\Cache;
use think\facade\Db;
use think\Model;


/**
 * @mixin think\Model
 */
class Statement extends Model
{
    use GetTableData;

    //需要统计的浏览器
    const BROWSERS = ['ie', 'firefox', 'chrome', 'opera', 'safari', 'unknown'];

    //缓存key
    const CACHE_BROWSER = 'cache_browser';
    const CACHE_COUNTS = 'cache_counts';
    const CACHE_PAGEVIEW = 'cache_pageview';
    const CACHE_IP = 'cache_ip';

    // 设置字段信息
    protected $schema = [
        'id'                => 'int',
        'session'           => 'string',
        'browser'           => 'string',
        'ip'                => 'int',
        'visited'           => 'int',
        'user_id'           => 'int',
        'create_time'       => 'int',
        'update_time'       => 'int',
    ];

    // 类型转换
    protected $type = [
        'id'                => 'integer',
        'ip'                => 'integer',
        'visited'           => 'integer',
        'user_id'           => 'integer',
    ];

    //关联用户
    public function user()
    {
        return $this->belongsTo(User::class,'user_id', 'id')->bind([
            'username' => 'showName',
            'avatar' => 'avatarUrl'
        ]);
    }

    //清空控制台缓存
    public static function chearCache(){
        Cache::delete(static::CACHE_IP);
        Cache::delete(static::CACHE_BROWSER);
        Cache::delete(static::CACHE_COUNTS);
        Cache::delete(static::CACHE_PAGEVIEW);
        return true;
    }

    //获取统计数字
    public static function getCounts(){
        if(!$counts = Cache::get(static::CACHE_COUNTS)){

            $counts = [
                'article' => Article::count(),
                'topic' => Topic::count(),
                'user' => User::count(),
                'tag'  => Tag::count()
            ];

            //设置缓存
            $expre = new \DateTime(date('Y-m-d 00:00:00', strtotime('+1 day')));
            Cache::set(static::CACHE_COUNTS, $counts, $expre);
        }
        return $counts;
    }

    //获取访问数据
    public static function getStatementListData(array $ruleWhere = []){
        //要查询的字段
        $fields = [
            'fields' =>['id','session', 'browser','ip','visited','user_id','update_time','create_time'],
            'with' => ['user'],
            'withCount' => [],
        ];

        //(构建查询条件)
        $where = [];
        if (input('start_time')){
            $where[] = ['create_time', '>=', strtotime(input('start_time'))];
        }
        if (input('end_time')){
            $where[] = ['create_time', '<=', strtotime( input('end_time'))];
        }

        //排序
        $order = ['id'=>'desc','create_time'=>'desc'];

        //[count:查询到的数目, list:记录列表]
        $data = static::operateDatum($where, $fields, $order,$ruleWhere);


        return [
            'count' => $data['count'],
            'data' => static::eachData($data['list'])
        ];
    }
    //遍历数据
    private static function eachData($list){
        foreach ($list as $k => &$v){
            $v['ip'] = long2ip($v['ip']);
        }
        return $list;
    }

    /**
     * 获取浏览器统计数据
     * @return array|mixed
     * @throws \Exception
     */
    public static function getBrowserListData(){
        if (!$browserList = Cache::get(static::CACHE_BROWSER)){
            $ret = Db::table('statement')
                ->group('browser')
                ->column('browser, COUNT(browser) AS count','browser');
            $data = [];
            foreach (static::BROWSERS as $v){
                $data[] = [
                    'name' => $v,
                    'value'=> $ret[$v]['count'] ?? 0
                ];
            }
            $browserList = [
                'keys' => static::BROWSERS,
                'data' => $data
            ];
            //缓存
            $expre = new \DateTime(date('Y-m-d 00:00:00', strtotime('+1 day')));
            Cache::set(static::CACHE_BROWSER, $browserList, $expre);
        }
        return $browserList;


    }


    /**
     * pv
     */
    public static function getPageview(){
        if (!$pageview = Cache::get(static::CACHE_PAGEVIEW)){
            $ret = [];
            $ret[date('l', strtotime('-7 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-7 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-7 day')))],
            ])->sum('visited');
            $ret[date('l', strtotime('-6 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-6 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-6 day')))],
            ])->sum('visited');
            $ret[date('l', strtotime('-5 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-5 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-5 day')))],
            ])->sum('visited');
            $ret[date('l', strtotime('-4 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-4 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-4 day')))],
            ])->sum('visited');
            $ret[date('l', strtotime('-3 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-3 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-3 day')))],
            ])->sum('visited');
            $ret[date('l', strtotime('-2 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-2 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-2 day')))],
            ])->sum('visited');
            $ret[date('l', strtotime('-1 day'))] = static::where([
                ['create_time', '>=', strtotime(date('Y-m-d 0:0:0', strtotime('-1 day')))],
                ['create_time', '<=', strtotime(date('Y-m-d 23:59:59', strtotime('-1 day')))],
            ])->sum('visited');
            $pageview = [
                'keys' => array_keys($ret),
                'sum' => array_values($ret)
            ];
            //缓存
            $expre = new \DateTime(date('Y-m-d 00:00:00', strtotime('+1 day')));
            Cache::set(static::CACHE_PAGEVIEW, $pageview, $expre);
        }
        return $pageview;

    }

    /**
     * 用户位置分布
     */
    public static function userLocation(){
        if(!$ipLocation = Cache::get(static::CACHE_IP)){
            $ret = Db::table('statement')
                ->group('ip')
                ->column('ip, COUNT(ip) AS count');

            $ipLocation = [];
            foreach ($ret as $k => $v){
                $name = (new IpLocation(long2ip($v['ip'])))->getProvince();

                if (!$name) continue;
                $ipLocation[] = [
                    'name' => $name,
                    'value'=> $v['count']
                ];
            }
            //缓存
            $expre = new \DateTime(date('Y-m-d 00:00:00', strtotime('+1 day')));
            Cache::set(static::CACHE_IP, $ipLocation, $expre);

        }

        return $ipLocation;
    }


}
